package room

import (
	"errors"
	"sync"

	"mmo/card/internal/config"
)

var (
	ErrRoomNotFound = errors.New("room not found")
	ErrRoomFull     = errors.New("room is full")
	ErrAlreadyInRoom = errors.New("already in room")
)

// RoomManager 是房间管理的抽象
type RoomManager interface {
	CreateRoom(roomID string, capacity int) (*GameRoom, error)
	GetRoom(roomID string) (*GameRoom, bool)
	Join(roomID, playerID string) (*GameRoom, error)
	Leave(roomID, playerID string) (*GameRoom, error)
	ListRooms() []RoomSummary
}

// RoomSummary 提供简要信息用于列表展示
type RoomSummary struct {
	ID          string
	Capacity    int
	PlayerCount int
	Phase       RoomPhase
}

// InMemoryRoomManager 基于内存的实现
type InMemoryRoomManager struct {
	mu    sync.RWMutex
	rooms map[string]*GameRoom
	cfg   config.GameConfig
}

func NewInMemoryRoomManager(cfg config.GameConfig) *InMemoryRoomManager {
	return &InMemoryRoomManager{
		rooms: make(map[string]*GameRoom),
		cfg:   cfg,
	}
}

func (m *InMemoryRoomManager) CreateRoom(roomID string, capacity int) (*GameRoom, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	if capacity <= 0 || capacity > m.cfg.MaxPlayersPerRoom {
		capacity = m.cfg.MaxPlayersPerRoom
	}
	if r, ok := m.rooms[roomID]; ok {
		return r, nil
	}
	r := NewGameRoom(roomID, capacity, m.cfg)
	m.rooms[roomID] = r
	return r, nil
}

func (m *InMemoryRoomManager) GetRoom(roomID string) (*GameRoom, bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	r, ok := m.rooms[roomID]
	return r, ok
}

func (m *InMemoryRoomManager) Join(roomID, playerID string) (*GameRoom, error) {
	r, ok := m.GetRoom(roomID)
	if !ok {
		var err error
		r, err = m.CreateRoom(roomID, m.cfg.MaxPlayersPerRoom)
		if err != nil {
			return nil, err
		}
	}
	return r.Join(playerID)
}

func (m *InMemoryRoomManager) Leave(roomID, playerID string) (*GameRoom, error) {
	r, ok := m.GetRoom(roomID)
	if !ok {
		return nil, ErrRoomNotFound
	}
	return r.Leave(playerID)
}

func (m *InMemoryRoomManager) ListRooms() []RoomSummary {
	m.mu.RLock()
	defer m.mu.RUnlock()
	res := make([]RoomSummary, 0, len(m.rooms))
	for _, r := range m.rooms {
		r.mu.RLock()
		s := RoomSummary{
			ID:          r.ID,
			Capacity:    r.Capacity,
			PlayerCount: len(r.players),
			Phase:       r.State.Phase,
		}
		r.mu.RUnlock()
		res = append(res, s)
	}
	return res
}